﻿#include <osgViewer/Viewer>

#include <osgDB/FileNameUtils>
#include <osgDB/FileUtils>
#include <osgDB/fstream>
#include <osgDB/Registry>
#include <osgDB/ReadFile>

#include <iostream>

template <class _Elem, class _Traits = std::char_traits<_Elem>>
class ReadStream : public std::basic_filebuf<_Elem, _Traits>
{
public:
	ReadStream(const std::string& filename) : _totalsize(0)
	{
		if (open(filename.c_str(), std::ios_base::in | std::ios_base::binary))
		{
			_totalsize = pubseekoff(0, std::ios_base::end, std::ios_base::in);
			std::cout << _totalsize << std::endl;
			pubseekoff(0, std::ios_base::beg, std::ios_base::in);
		}
	}

protected:
	// 显示读取进度，支持osg格式，ive格式不会进到这个函数里。
	virtual int_type uflow()
	{
		int_type value = std::basic_filebuf<_Elem, _Traits>::uflow();
		current += (egptr() - gptr());
		std::cout << (float)current/_totalsize * 100 << "%" << std::endl;
		return value;
	}

	int current = 0;
	int _totalsize;
};

class ReadFileCB : public osgDB::Registry::ReadFileCallback
{
public:
	typedef ReadStream<char> ReadStreamString;
	virtual osgDB::ReaderWriter::ReadResult readNode(const std::string& file, const osgDB::ReaderWriter::Options* opt)
	{
        // 第一步是获取OSG、IVE ReaderWriter
        std::string ext = osgDB::getLowerCaseFileExtension(file);
		osgDB::ReaderWriter* rw = osgDB::Registry::instance()->getReaderWriterForExtension(ext);

		if (!rw)
		{
			return osgDB::ReaderWriter::ReadResult::FILE_NOT_HANDLED;
		}

        std::string fileName = osgDB::findDataFile(file, opt);
        if (fileName.empty()) return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;

        //osgDB::ifstream fin(fileName.c_str());
		ReadStreamString* fin = new ReadStreamString(fileName);

		if (fin->is_open())
		{
			std::cout << "using default format readerwriter" << std::endl;
			return rw->readNode(std::istream(fin));
		}
		else
		{
			return osgDB::ReaderWriter::ReadResult::ERROR_IN_READING_FILE;
		}


		//std::cout << "use ouer function" << std::endl;
		//return osgDB::Registry::instance()->readNodeImplementation(file, opt);
	}
};

int main()
{
	osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
	osgDB::Registry::instance()->setReadFileCallback(new ReadFileCB);
	osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("glider.osg");
	viewer->setSceneData(node);
	viewer->setUpViewInWindow(100, 100, 800, 600);
	return viewer->run();
}